package com.byapp.fast.modules.order.controller;

import com.byapp.fast.common.enums.ResultEnum;
import com.byapp.fast.common.exception.BYException;
import com.byapp.fast.common.utils.JsonUtils;
import com.byapp.fast.common.utils.PlayIdUtils;
import com.byapp.fast.common.utils.ResultUtils;
import com.byapp.fast.common.validator.ValidatorUtils;
import com.byapp.fast.common.vo.ResultVO;
import com.byapp.fast.modules.match.service.MatchService;
import com.byapp.fast.modules.order.dto.OrderDTO;
import com.byapp.fast.modules.order.dto.OrderDataDTO;
import com.byapp.fast.modules.order.dto.OrderItemDTO;
import com.byapp.fast.modules.order.service.OrderService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StopWatch;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.byapp.fast.common.utils.PlayIdUtils.getPlayItems;

@RestController("/order")
@Api(value = "订单模块接口", tags = {"订单模块接口"})
@Slf4j
public class OrderController {

    @Autowired
    private OrderService orderService;

    @Autowired
    private MatchService matchService;

    @PostMapping("/buy")
    @ApiOperation(value = "赛事竞猜操作", notes = "赛事竞猜操作")
    @ApiImplicitParam(name = "orderDTO", value = "竞猜实体", required = true, dataType = "OrderDTO")
    public ResultVO buy(@RequestBody OrderDTO orderDTO) {
        StopWatch stopWatch = new StopWatch("buy");

        // 参数校验
        stopWatch.start("参数校验");
        ValidatorUtils.validateEntity(orderDTO);
        ValidatorUtils.validateEntity(orderDTO.getOrderDataDTO());
        ValidatorUtils.validateEntity(orderDTO.getOrderDataDTO().getItemsList());
        stopWatch.stop();

        // TODO： 校验是否重复提交：基于redis的计数器实现

        // 获取请求参数
        OrderDataDTO orderDataDTO = orderDTO.getOrderDataDTO();
        List<OrderItemDTO> itemsList = orderDataDTO.getItemsList();

        stopWatch.start("校验赛事是否开始");
        long count = itemsList.stream()
                .map(item -> matchService.isMatchStarted(item.getMatchId()))
                .distinct()
                .filter(flag -> flag)
                .count();
        if (count > 0) {
            log.error("【赛事竞猜】赛事已开始，OrderDataDTO={}", JsonUtils.toJson(orderDataDTO));
            throw new BYException(ResultEnum.ILLEGAL_PARAM);
        }
        stopWatch.stop();


        stopWatch.start("校验赛事是否开盘");
        // 校验赛事是否开盘
        count = itemsList.stream()
                .map(item -> matchService.isMatchBetEnabled(item.getMatchId()))
                .distinct()
                .filter(flag -> !flag)
                .count();
        if (count > 0) {
            log.error("【赛事竞猜】赛事已封盘，OrderDataDTO={}", JsonUtils.toJson(orderDataDTO));
            throw new BYException(ResultEnum.ILLEGAL_PARAM);
        }
        stopWatch.stop();

        // 校验玩法是否开盘
        stopWatch.start("校验玩法是否开盘");
        count = itemsList.stream()
                .map(item -> {
                    String playId = item.getPlayId();
                    String[] plays = getPlayItems(playId);
                    Map<String, Object> params = new HashMap<>();
                    params.put("MATCH_ID", item.getMatchId());
                    params.put("HANDICAP_VALUE", item.getHandicap());
                    params.put("ODDS_PHASE", 2);
                    params.put("BET_TYPE", plays[0]);
                    params.put("MATCH_PHASE", plays[1]);
                    params.put("STATUS", 0);
                    return matchService.isPlayBetEnabled(params);
                })
                .distinct()
                .filter(flag -> !flag)
                .count();
        if (count > 0) {
            log.error("【赛事竞猜】玩法已封盘，OrderDataDTO={}", JsonUtils.toJson(orderDataDTO));
            throw new BYException(ResultEnum.ILLEGAL_PARAM);
        }
        stopWatch.stop();

        // 校验赔率/盘口变化
        stopWatch.start("校验赔率/盘口是否变化");
        count = itemsList.stream()
                .map(item -> {
                    String playId = item.getPlayId();
                    String[] plays = PlayIdUtils.getPlayItems(playId);
                    Map<String, Object> params = new HashMap<>();
                    params.put("MATCH_ID", item.getMatchId());
                    params.put("HANDICAP_VALUE", item.getHandicap());
                    params.put("CODES", item.getCodes());
                    params.put("ODDS", item.getOdds());
                    params.put("ODDS_PHASE", 2);
                    params.put("STATUS", 0);
                    params.put("PLAY", plays[0]);
                    params.put("MATCH_PHASE", plays[1]);
                    return matchService.isOriginOddsAndHandicap(params);
                })
                .distinct()
                .filter(flag -> !flag)
                .count();
        if (count > 0) {
            log.error("【赛事竞猜】赔率/盘口发生变化，OrderDataDTO={}", JsonUtils.toJson(orderDataDTO));
            throw new BYException(ResultEnum.ILLEGAL_PARAM);
        }
        stopWatch.stop();

        // 生成订单
        stopWatch.start("竞猜下单");
        orderService.createWebOrder(orderDataDTO);
        stopWatch.stop();

        log.info("【执行日志】{}", stopWatch.prettyPrint());
        return ResultUtils.success();
    }


}
